home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 16
/
Aminet 16 (1996)(GTI - Schatztruhe)[!][Dec 1996].iso
/
Aminet
/
comm
/
term
/
term_source.lha
/
Extras
/
Source
/
term-source.lha
/
Tools.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-10-20
|
74KB
|
4,113 lines
/*
** Tools.c
**
** Miscellaneous support routines
**
** Copyright © 1990-1996 by Olaf `Olsen' Barthel
** All Rights Reserved
**
** :ts=4
*/
#ifndef _GLOBAL_H
#include "Global.h"
#endif
/* Current timer state. */
STATIC BOOL TimerRunning;
/* ListViewStateFill(struct LVDrawMsg *Msg):
*
* Draw the ghosting pattern over a ghosted listview line.
*/
VOID
ListViewStateFill(struct LVDrawMsg *Msg)
{
if(Msg->lvdm_State == LVR_SELECTEDDISABLED || Msg->lvdm_State == LVR_NORMALDISABLED)
{
struct RastPort *RPort = Msg->lvdm_RastPort;
ULONG Ghosting = 0x44441111;
SetABPenDrMd(RPort,Msg->lvdm_DrawInfo->dri_Pens[SHADOWPEN],0,JAM1);
SetAfPt(RPort,(UWORD *)&Ghosting,1);
RectFill(RPort,Msg->lvdm_Bounds.MinX,Msg->lvdm_Bounds.MinY,Msg->lvdm_Bounds.MaxX,Msg->lvdm_Bounds.MaxY);
SetAfPt(RPort,NULL,0);
}
}
/* EraseWindow(struct Window *Window):
*
* Fills the interior of a window in the background colour.
*/
VOID
EraseWindow(struct Window *Window,UWORD *Pens)
{
LONG Left,Top,Right,Bottom;
Left = Window->BorderLeft;
Top = Window->BorderTop;
Right = Window->Width - (Window->BorderRight + 1);
Bottom = Window->Height - (Window->BorderBottom + 1);
if(Pens)
{
SetPens(RPort,Pens[BACKGROUNDPEN],0,JAM1);
RectFill(Window->RPort,Left,Top,Right,Bottom);
}
else
EraseRect(Window->RPort,Left,Top,Right,Bottom);
}
/* GetListMaxPen(UWORD *Pens):
*
* Calculates the maximum pen number index to be
* used for listview text rendering.
*/
LONG
GetListMaxPen(UWORD *Pens)
{
STATIC BYTE PenTable[] =
{
TEXTPEN,
BACKGROUNDPEN,
FILLTEXTPEN,
FILLPEN,
SHADOWPEN,
HIGHLIGHTTEXTPEN,
};
LONG Max,Pen,i;
for(i = 0, Max = -1 ; i < NUM_ELEMENTS(PenTable) ; i++)
{
Pen = Pens[PenTable[i]];
if(Pen > Max)
Max = Pen;
}
return(Max);
}
/* FillBox(struct RastPort *RPort,LONG Left,LONG Top,LONG Width,LONG Height):
*
* Fill a rectangular area with the current foregroung colour.
*/
VOID
FillBox(struct RastPort *RPort,LONG Left,LONG Top,LONG Width,LONG Height)
{
if(Width > 0 && Height > 0)
RectFill(RPort,Left,Top,Left + Width - 1,Top + Height - 1);
}
VOID
FillWindowBox(struct Window *Window,LONG Left,LONG Top,LONG Width,LONG Height)
{
if(Left + Width > WindowWidth)
Width = WindowWidth - Left - 1;
if(Top + Height > WindowHeight)
Height = WindowHeight - Top - 1;
if(Width > 0 && Height > 0)
{
Left += Window->BorderLeft;
Top += Window->BorderTop;
RectFill(Window->RPort,Left,Top,Left + Width - 1,Top + Height - 1);
}
}
/* PlaceText(struct RastPort *RPort,LONG Left,LONG Top,STRPTR String,LONG Len):
*
* Print some text at a specific position.
*/
VOID
PlaceText(struct RastPort *RPort,LONG Left,LONG Top,STRPTR String,LONG Len)
{
Move(RPort,Left,Top + RPort->TxBaseline);
Text(RPort,String,Len);
}
/* SetPens(struct RastPort *RPort,ULONG APen,ULONG BPen,ULONG DrMd):
*
* Set rendering attributes.
*/
VOID
SetPens(struct RastPort *RPort,ULONG APen,ULONG BPen,ULONG DrMd)
{
if(Kick30)
SetABPenDrMd(RPort,APen,BPen,DrMd);
else
{
if(APen != RPort->FgPen)
SetAPen(RPort,APen);
if(BPen != RPort->BgPen)
SetBPen(RPort,BPen);
if(DrMd != RPort->DrawMode)
SetDrMd(RPort,DrMd);
}
}
/* Atol(STRPTR Buffer):
*
* Convert ASCII representation to long word.
*/
LONG
Atol(STRPTR Buffer)
{
LONG Result;
StrToLong(Buffer,&Result);
return(Result);
}
/* StripSpaces(STRPTR String):
*
* Strip leading and trailing spaces from a string.
*/
VOID
StripSpaces(STRPTR String)
{
if(String)
{
STRPTR To;
LONG Len;
To = String;
while(*String == ' ')
String++;
if(Len = strlen(String))
{
while(Len > 0 && String[Len - 1] == ' ')
Len--;
while(Len--)
*To++ = *String++;
}
*To = 0;
}
}
/* ReplaceWindowInfo(struct WindowInfo *NewInfo):
*
* Drop the window info into the right place.
*/
VOID
ReplaceWindowInfo(struct WindowInfo *NewInfo)
{
LONG i;
ObtainSemaphore(&WindowInfoSemaphore);
for(i = 0 ; WindowInfoTable[i].ID != -1 ; i++)
{
if(WindowInfoTable[i].ID == NewInfo->ID)
{
CopyMem(NewInfo,&WindowInfoTable[i],sizeof(struct WindowInfo));
break;
}
}
ReleaseSemaphore(&WindowInfoSemaphore);
}
/* PutWindowInfo():
*
* Store window size and position relative to
* the main window.
*/
VOID
PutWindowInfo(LONG ID,LONG Left,LONG Top,LONG Width,LONG Height)
{
LONG WindowLeft,WindowTop,WindowWidth,WindowHeight;
struct WindowInfo *Info;
ULONG IntuiLock;
LONG i;
ObtainSemaphore(&WindowInfoSemaphore);
for(i = 0 ; WindowInfoTable[i].ID != -1 ; i++)
{
if(WindowInfoTable[i].ID == ID)
{
Info = &WindowInfoTable[i];
break;
}
}
IntuiLock = LockIBase(NULL);
WindowLeft = Window->LeftEdge;
WindowTop = Window->TopEdge;
WindowWidth = Window->Width;
WindowHeight = Window->Height;
UnlockIBase(IntuiLock);
Info->WindowFlags = NULL;
if(WindowWidth == Width && WindowLeft == Left)
Info->WindowFlags |= WC_EXPANDWIDTH;
else
{
if(Left == WindowLeft + WindowWidth)
Info->WindowFlags |= WC_ALIGNSIDE;
if(WindowLeft == Left)
Info->WindowFlags |= WC_ALIGNLEFT;
if(WindowLeft + WindowWidth == Left + Width)
Info->WindowFlags |= WC_ALIGNRIGHT;
}
if(WindowHeight == Height && WindowTop + Window->BorderTop == Top)
Info->WindowFlags |= WC_EXPANDHEIGHT;
else
{
if(Top == WindowTop + WindowHeight)
Info->WindowFlags |= WC_ALIGNBELOW;
if(Top == WindowTop + Window->BorderTop)
Info->WindowFlags |= WC_ALIGNTOP;
if(WindowTop + WindowHeight == Top + Height)
Info->WindowFlags |= WC_ALIGNBOTTOM;
}
Info->Left = Left;
Info->Top = Top;
Info->Width = Width;
Info->Height = Height;
ReleaseSemaphore(&WindowInfoSemaphore);
}
/* GetWindowInfo():
*
* Set the window size and position in relation to
* the main window.
*/
VOID
GetWindowInfo(LONG ID,LONG *Left,LONG *Top,LONG *Width,LONG *Height,LONG DefWidth,LONG DefHeight)
{
LONG WindowLeft,WindowTop,WindowWidth,WindowHeight;
struct WindowInfo *Info;
ULONG IntuiLock;
LONG i;
SafeObtainSemaphoreShared(&WindowInfoSemaphore);
Info = NULL;
for(i = 0 ; WindowInfoTable[i].ID != -1 ; i++)
{
if(WindowInfoTable[i].ID == ID)
{
Info = &WindowInfoTable[i];
break;
}
}
if(Info && ID == WINDOW_MAIN)
{
*Left = Info->Left;
*Top = Info->Top;
*Width = Info->Width;
*Height = Info->Height;
}
else
{
if(Window)
{
IntuiLock = LockIBase(NULL);
WindowLeft = Window->LeftEdge;
WindowTop = Window->TopEdge;
WindowWidth = Window->Width;
WindowHeight = Window->Height;
UnlockIBase(IntuiLock);
if(DefWidth && DefWidth < WindowWidth / 2)
DefWidth = WindowWidth / 2;
if(DefHeight && DefHeight < WindowHeight / 2)
DefHeight = WindowHeight / 2;
}
if(*Width)
{
if(Info->Width)
*Left = Info->Left;
else
*Left = WindowLeft + (WindowWidth - *Width) / 2;
}
else
{
if(DefWidth && !Info->Width)
{
*Width = DefWidth;
*Left = WindowLeft + (WindowWidth - *Width) / 2;
}
else
{
if(Info->Width)
{
*Width = Info->Width;
*Left = Info->Left;
}
else
{
*Width = WindowWidth;
*Left = WindowLeft;
}
}
}
if(*Height)
{
if(Info->Height)
*Top = Info->Top;
else
*Top = WindowTop + (WindowHeight - *Height) / 2;
}
else
{
if(DefHeight && !Info->Height)
{
*Height = DefHeight;
*Top = WindowTop + (WindowHeight - *Height) / 2;
}
else
{
if(Info->Height)
{
*Height = Info->Height;
*Top = Info->Top;
}
else
{
*Height = WindowHeight;
*Top = WindowTop;
}
}
}
if(Info->WindowFlags & WC_ALIGNSIDE)
*Left = WindowLeft + WindowWidth;
if(Info->WindowFlags & WC_ALIGNBELOW)
*Top = WindowTop + WindowHeight;
if(Info->WindowFlags & WC_ALIGNLEFT)
*Left = WindowLeft;
if(Info->WindowFlags & WC_ALIGNTOP)
*Top = WindowTop;
if(Info->WindowFlags & WC_ALIGNRIGHT)
*Left = WindowLeft + WindowWidth - *Width;
if(Info->WindowFlags & WC_ALIGNBOTTOM)
*Top = WindowTop + WindowHeight - *Height;
if(Info->WindowFlags & WC_EXPANDWIDTH)
*Width = WindowWidth;
if(Info->WindowFlags & WC_EXPANDHEIGHT)
*Height = WindowHeight;
if(*Top == WindowTop && *Left == WindowLeft)
{
LONG TitleHeight = Window->BorderTop;
if(*Height == WindowHeight)
*Height -= TitleHeight;
*Top += TitleHeight;
}
}
ReleaseSemaphore(&WindowInfoSemaphore);
}
/* GetBitMapDepth(struct BitMap *BitMap):
*
* Return the depth of a BitMap.
*/
LONG
GetBitMapDepth(struct BitMap *BitMap)
{
LONG Depth;
if(Kick30)
Depth = (LONG)GetBitMapAttr(BitMap,BMA_DEPTH);
else
Depth = BitMap->Depth;
if(Depth > 8)
Depth = 8;
return(Depth);
}
/* GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI):
*
* Get screen DPI resolution values.
*/
VOID
GetDPI(ULONG Mode,ULONG *X_DPI,ULONG *Y_DPI)
{
struct DisplayInfo DisplayInfo;
*X_DPI = *Y_DPI = 72;
if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,Mode))
{
if(DisplayInfo.PixelSpeed && DisplayInfo.Resolution.x && DisplayInfo.Resolution.y)
{
*X_DPI = (35 * 140) / DisplayInfo.PixelSpeed;
*Y_DPI = (*X_DPI * DisplayInfo.Resolution.x) / DisplayInfo.Resolution.y;
}
}
}
/* AddProtection(STRPTR FileName,ULONG Mask):
*
* Set bits in the protection mask of a file.
*/
VOID
AddProtection(STRPTR Name,ULONG Mask)
{
BPTR FileLock;
D_S(struct FileInfoBlock,FileInfo);
if(FileLock = Lock(Name,ACCESS_READ))
{
if(Examine(FileLock,FileInfo))
{
UnLock(FileLock);
if(Mask == FIBF_EXECUTE)
Mask |= FileInfo->fib_Protection & ~(FIBF_OTR_EXECUTE|FIBF_GRP_EXECUTE);
else
Mask |= FileInfo->fib_Protection;
SetProtection(Name,Mask);
}
else
UnLock(FileLock);
}
}
/* GetPubScreenName(struct Screen *Screen,STRPTR Name):
*
* Get the name of a public screen.
*/
BOOL
GetPubScreenName(struct Screen *Screen,STRPTR Name)
{
struct List *PubScreenList;
struct PubScreenNode *ScreenNode;
BOOL GotIt;
PubScreenList = LockPubScreenList();
for(ScreenNode = (struct PubScreenNode *)PubScreenList->lh_Head, GotIt = FALSE ; !GotIt && ScreenNode->psn_Node.ln_Succ ; ScreenNode = (struct PubScreenNode *)ScreenNode->psn_Node.ln_Succ)
{
if(ScreenNode->psn_Screen == Screen)
{
strcpy(Name,ScreenNode->psn_Node.ln_Name);
GotIt = TRUE;
}
}
UnlockPubScreenList();
return(GotIt);
}
/* InitSinglePort(struct MsgPort *Port):
*
* Initialize a plain MsgPort (as created on the stack) for
* usage. Don't try this at home, kids!
*/
VOID
InitSinglePort(struct MsgPort *Port)
{
memset(Port,0,sizeof(struct MsgPort));
Port->mp_Flags = PA_SIGNAL;
Port->mp_SigBit = SIGB_SINGLE;
Port->mp_SigTask = FindTask(NULL);
NewList(&Port->mp_MsgList);
}
/* GoodStream(BPTR Stream):
*
* Check to see whether the current input file
* is an interactive stream.
*/
BOOL
GoodStream(BPTR Stream)
{
if(!Stream)
Stream = Input();
if(Stream)
{
struct FileHandle *Handle = (struct FileHandle *)BADDR(Stream);
if(Handle->fh_Type)
{
if(IsInteractive(Stream))
return(TRUE);
}
}
return(FALSE);
}
/* GetProgramIcon():
*
* Try to find the icon of the program.
*/
struct DiskObject *
GetProgramIcon()
{
struct DiskObject *Icon = NULL;
/* Run from Workbench? */
if(WBenchMsg)
{
/* Sanity check. */
if(WBenchMsg->sm_ArgList)
{
/* Yet another sanity check. */
if(WBenchMsg->sm_ArgList->wa_Name)
{
/* Try to find the icon in the current directory. */
if(Icon = GetDiskObjectNew(WBenchMsg->sm_ArgList->wa_Name))
{
if(Icon->do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
if(!Icon)
{
BPTR NewLock;
/* Move to the directory the
* program was run from.
*/
if(NewLock = Lock("PROGDIR:",ACCESS_READ))
{
BPTR OldLock;
OldLock = CurrentDir(NewLock);
/* Try to fetch the icon, use the
* default name if necessary.
*/
if(Icon = GetDiskObjectNew(WBenchMsg->sm_ArgList->wa_Name))
{
if(Icon->do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
if(!Icon)
{
if(Icon = GetDiskObjectNew("term"))
{
if(Icon->do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
}
CurrentDir(OldLock);
UnLock(NewLock);
}
}
}
}
}
/* Still no success. */
if(!Icon)
{
/* Use the default names. */
if(Icon = GetDiskObjectNew("term"))
{
if(Icon->do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
if(!Icon)
{
if(Icon = GetDiskObjectNew("PROGDIR:term"))
{
if(Icon->do_Type != WBTOOL)
{
FreeDiskObject(Icon);
Icon = NULL;
}
}
}
}
return(Icon);
}
/* GetPenIndex(LONG Pen):
*
* Get the table index corresponding to an on-screen
* text rendering pen.
*/
LONG
GetPenIndex(LONG Pen)
{
LONG i,Result = 0;
for(i = 0 ; i < 16 ; i++)
{
if(MappedPens[0][i] == Pen)
{
Result = i;
break;
}
}
return(Result);
}
/* GetScreenWidth(struct Window *Window):
*
* Query the current screen width.
*/
LONG
GetScreenWidth(struct Window *Window)
{
if(Window)
{
if(Window->Width > ScreenWidth || Window->LeftEdge < -Window->WScreen->LeftEdge || Window->LeftEdge + Window->WScreen->LeftEdge + Window->Width > ScreenWidth)
return(ScreenWidth);
else
return(Window->Width - (Window->BorderLeft + Window->BorderRight));
}
else
return(ScreenWidth);
}
/* GetScreenHeight(struct Window *Window):
*
* Query the current screen height.
*/
LONG
GetScreenHeight(struct Window *Window)
{
if(Window)
{
if(Window->Height > ScreenHeight || Window->TopEdge < -Window->WScreen->TopEdge || Window->TopEdge + Window->WScreen->TopEdge + Window->Height > ScreenHeight)
return(ScreenHeight);
else
return(Window->Height - (Window->BorderTop + Window->BorderBottom));
}
else
return(ScreenHeight);
}
/* GetLeft(struct Screen *Screen):
*
* Get the screen left edge.
*/
STATIC LONG
GetLeft(struct Screen *Screen)
{
if(Screen->LeftEdge >= 0)
return(0);
else
return(-Screen->LeftEdge);
}
/* GetScreenLeft(struct Window *Window):
*
* Query the current screen left edge.
*/
LONG
GetScreenLeft(struct Window *Window)
{
if(Window)
{
if(Window->Width > ScreenWidth || Window->LeftEdge < -Window->WScreen->LeftEdge || Window->LeftEdge + Window->WScreen->LeftEdge + Window->Width > ScreenWidth)
return(GetLeft(Window->WScreen));
else
return(Window->LeftEdge + Window->BorderLeft);
}
else
{
struct Screen *PubScreen = LockPubScreen(NULL);
LONG Result;
Result = GetLeft(PubScreen ? PubScreen : SharedScreen);
UnlockPubScreen(NULL,PubScreen);
return(Result);
}
}
/* OldGetAPen(struct RastPort *RPort):
*
* Query the current primary rendering colour (old style).
*/
ULONG
OldGetAPen(struct RastPort *RPort)
{
return((ULONG)RPort->FgPen);
}
/* OldGetBPen(struct RastPort *RPort):
*
* Query the current seconary rendering colour (old style).
*/
ULONG
OldGetBPen(struct RastPort *RPort)
{
return((ULONG)RPort->BgPen);
}
/* OldGetDrMd(struct RastPort *RPort):
*
* Query the current drawing mode (old style).
*/
ULONG
OldGetDrMd(struct RastPort *RPort)
{
return((ULONG)RPort->DrawMode);
}
/* OldSetWrMsk(struct RastPort *RPort,ULONG Mask):
*
* Set the rendering plane mask (old style).
*/
ULONG
OldSetWrMsk(struct RastPort *RPort,ULONG Mask)
{
if(UseMasking)
RPort->Mask = Mask;
return((ULONG)1);
}
/* OldGetWrMsk(struct RastPort *RPort):
*
* Get the rendering plane mask (old style).
*/
ULONG
OldGetWrMsk(struct RastPort *RPort)
{
return(RPort->Mask);
}
/* NewGetAPen(struct RastPort *RPort):
*
* Query the current primary rendering colour (new style).
*/
ULONG
NewGetAPen(struct RastPort *RPort)
{
return(GetAPen(RPort));
}
/* NewGetBPen(struct RastPort *RPort):
*
* Query the current seconary rendering colour (new style).
*/
ULONG
NewGetBPen(struct RastPort *RPort)
{
return(GetBPen(RPort));
}
/* NewGetDrMd(struct RastPort *RPort):
*
* Query the current drawing mode (new style).
*/
ULONG
NewGetDrMd(struct RastPort *RPort)
{
return(GetDrMd(RPort));
}
/* NewSetWrMsk(struct RastPort *RPort,ULONG Mask):
*
* Set the rendering plane mask (new style).
*/
ULONG
NewSetWrMsk(struct RastPort *RPort,ULONG Mask)
{
if(UseMasking)
return(SetWriteMask(RPort,Mask));
else
return((ULONG)1);
}
/* NewGetWrMsk(struct RastPort *RPort):
*
* Get the rendering plane mask (new style).
*/
ULONG
NewGetWrMsk(struct RastPort *RPort)
{
ULONG Mask;
Mask = (ULONG)~0;
GetRPAttrs(RPort,
RPTAG_WriteMask,&Mask,
TAG_DONE);
return(Mask);
}
/* SetWait(struct Window *Window):
*
* Set the busy wait mouse pointer.
*/
VOID
SetWait(struct Window *Window)
{
if(GTLayoutBase)
LT_LockWindow(Window);
}
/* ClrWait(struct Window *Window):
*
* Remove the busy wait mouse pointer.
*/
VOID
ClrWait(struct Window *Window)
{
if(GTLayoutBase)
LT_UnlockWindow(Window);
}
/* GetModeName(ULONG Mode):
*
* Get the name of a display mode.
*/
VOID
GetModeName(ULONG Mode,STRPTR Buffer,LONG BufferSize)
{
struct NameInfo NameInfo;
if(GetDisplayInfoData(NULL,(APTR)&NameInfo,sizeof(struct NameInfo),DTAG_NAME,Mode))
LimitedStrcpy(BufferSize,Buffer,NameInfo.Name);
else
{
struct DimensionInfo DimensionInfo;
if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,Mode))
{
STRPTR MonitorName;
switch(Mode & MONITOR_ID_MASK)
{
case NTSC_MONITOR_ID:
MonitorName = "NTSC:";
break;
case PAL_MONITOR_ID:
MonitorName = "PAL:";
break;
case VGA_MONITOR_ID:
MonitorName = "VGA:";
break;
case A2024_MONITOR_ID:
MonitorName = "A2024:";
break;
default:
MonitorName = "";
break;
}
LimitedSPrintf(BufferSize,Buffer,"%s%ldx%ld",MonitorName,DimensionInfo.TxtOScan.MaxX - DimensionInfo.TxtOScan.MinX + 1,DimensionInfo.TxtOScan.MaxY - DimensionInfo.TxtOScan.MinY + 1);
}
else
LimitedStrcpy(BufferSize,Buffer,LocaleString(MSG_SCREENPANEL_UNKNOWN_TXT));
}
}
/* ModeOkay(ULONG ID):
*
* Checks whether a display mode ID will do for deep
* screen bitmaps.
*/
BOOL
ModeOkay(ULONG ID)
{
struct DimensionInfo DimensionInfo;
if(GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(struct DimensionInfo),DTAG_DIMS,ID))
{
if(DimensionInfo.MaxDepth >= 4)
return(TRUE);
}
return(FALSE);
}
/* ExtractString():
*
* Extracts a string from a list separated by `|' characters.
*/
STRPTR
ExtractString(STRPTR String,STRPTR Destination,BOOL ReturnEnd)
{
STRPTR OldString;
if(ReturnEnd)
OldString = NULL;
else
OldString = String;
while(*String)
{
if(*String == '|')
{
*Destination = 0;
String++;
if(*String)
return(String);
else
return(OldString);
}
else
*Destination++ = *String++;
}
*Destination = 0;
return(OldString);
}
/* RemoveGetNext(struct Node *Node):
*
* Remove a node from a list and return the `next'
* node to take its place.
*/
struct Node *
RemoveGetNext(struct Node *Node)
{
struct Node *Next;
/* Does the node have a successor? */
if(Node->ln_Succ->ln_Succ)
Next = Node->ln_Succ;
else
{
/* Does it have a predecessor? */
if(Node->ln_Pred->ln_Pred)
Next = Node->ln_Pred;
else
Next = NULL;
}
/* Remove the old node. */
Remove(Node);
/* And return the node to take its place. */
return(Next);
}
/* GetListSize(struct List *List):
*
* Determine the number of entries in a list.
*/
LONG
GetListSize(struct List *List)
{
struct Node *Node;
LONG i;
for(Node = List->lh_Head, i = 0 ; Node->ln_Succ ; Node = Node->ln_Succ, i++);
return(i);
}
/* GetListNode(LONG Offset,struct List *List):
*
* Return the n-th Node entry in a standard exec list.
*/
struct Node *
GetListNode(LONG Offset,struct List *List)
{
struct Node *Node;
LONG Index;
for(Node = List->lh_Head, Index = 0 ; Node->ln_Succ ; Node = Node->ln_Succ, Index++)
{
if(Index == Offset)
return(Node);
}
return(NULL);
}
/* CreateNode(STRPTR Name):
*
* Put a name string into a list node.
*/
struct Node *
CreateNode(STRPTR Name)
{
struct Node *Node;
if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + strlen(Name) + 1,MEMF_ANY))
strcpy(Node->ln_Name = (STRPTR)(Node + 1),Name);
return(Node);
}
/* CreateNodeArgs(STRPTR Format,...):
*
* Put a name string into a list node, varargs version.
*/
struct Node *
CreateNodeArgs(STRPTR Format,...)
{
UBYTE LocalBuffer[256];
struct Node *Node;
va_list VarArgs;
va_start(VarArgs,Format);
LimitedVSPrintf(sizeof(LocalBuffer),LocalBuffer,Format,VarArgs);
va_end(VarArgs);
if(Node = (struct Node *)AllocVecPooled(sizeof(struct Node) + strlen(LocalBuffer) + 1,MEMF_ANY))
strcpy(Node->ln_Name = (STRPTR)(Node + 1),LocalBuffer);
return(Node);
}
/* FormatAppend(STRPTR String,STRPTR Format,...):
*
* Appends a formatted string to another string.
*/
VOID
FormatAppend(STRPTR String,STRPTR Format,...)
{
va_list VarArgs;
String += strlen(String);
va_start(VarArgs,Format);
VSPrintf(String,Format,VarArgs);
va_end(VarArgs);
}
/* FreeList(struct List *List):
*
* Remove all nodes from the list
* and free them on the way.
*/
VOID
FreeList(struct List *List)
{
if(List)
{
struct Node *Node;
while(Node = RemHead(List))
FreeVecPooled(Node);
}
}
/* GetNodeOffset(struct Node *Node,struct List *List):
*
* Scan a list for a certain node and return
* its position.
*/
LONG
GetNodeOffset(struct Node *ListNode,struct List *List)
{
if(ListNode && List)
{
struct Node *Node;
LONG Offset;
for(Node = List->lh_Head, Offset = 0 ; Node->ln_Succ ; Node = Node->ln_Succ, Offset++)
{
if(Node == ListNode)
return(Offset);
}
}
return(-1);
}
/* MoveList(struct List *From,struct List *To):
*
* Move the contents of a list to a different list.
*/
VOID
MoveList(struct List *From,struct List *To)
{
struct Node *Node;
while(Node = RemHead(From))
AddTail(To,Node);
}
/* CreateList():
*
* Create a small, empty list.
*/
struct List *
CreateList()
{
struct List *List;
if(List = (struct List *)AllocVecPooled(sizeof(struct MinList),MEMF_ANY))
NewList(List);
return(List);
}
/* DeleteList():
*
* Free the contents of a list and the list itself.
*/
VOID
DeleteList(struct List *List)
{
if(List)
{
struct Node *Node,*Next;
for(Node = List->lh_Head ; Next = Node->ln_Succ ; Node = Next)
FreeVecPooled(Node);
FreeVecPooled(List);
}
}
/* MoveNode(struct List *List,struct Node *Node,LONG How):
*
* Move a list node somewhere.
*/
VOID
MoveNode(struct List *List,struct Node *Node,LONG How)
{
switch(How)
{
case MOVE_HEAD:
if(Node != List->lh_Head)
{
Remove(Node);
AddHead(List,Node);
}
break;
case MOVE_PRED:
if(Node != List->lh_Head)
{
struct Node *Other;
Other = Node->ln_Pred->ln_Pred;
Remove(Node);
Insert(List,Node,Other);
}
break;
case MOVE_SUCC:
if(Node != List->lh_TailPred)
{
struct Node *Other;
Other = Node->ln_Succ;
Remove(Node);
Insert(List,Node,Other);
}
break;
case MOVE_TAIL:
if(Node != List->lh_TailPred)
{
Remove(Node);
AddTail(List,Node);
}
break;
}
}
/* LogAction(STRPTR String,...):
*
* Write an action to the default log file.
*/
VOID
LogAction(STRPTR String,...)
{
if(Config->CaptureConfig->LogActions && Config->CaptureConfig->LogFileName[0])
{
UBYTE DummyBuffer[512];
BPTR File;
BOOL Created;
va_list VarArgs;
/* Build a valid string. */
va_start(VarArgs,String);
LimitedVSPrintf(sizeof(DummyBuffer),DummyBuffer,String,VarArgs);
va_end(VarArgs);
/* Open the log file. */
if(File = OpenToAppend(Config->CaptureConfig->LogFileName,&Created))
{
if(Created)
FPrintf(File,LocaleString(MSG_TERMAUX_DATE_TIME_ACTION_TXT));
}
/* The file is open, build the date/time string and
* write the log action.
*/
if(File)
{
UBYTE DateBuffer[40],
TimeBuffer[40];
struct DateTime DateTime;
DateStamp(&DateTime.dat_Stamp);
DateTime.dat_Format = FORMAT_DEF;
DateTime.dat_Flags = NULL;
DateTime.dat_StrDay = NULL;
DateTime.dat_StrDate = DateBuffer;
DateTime.dat_StrTime = TimeBuffer;
if(DateToStr(&DateTime))
{
StripSpaces(TimeBuffer);
FPrintf(File,"%-9s %8s %s\n",DateBuffer,TimeBuffer,DummyBuffer);
}
/* Done! */
Close(File);
}
}
}
/* GetString(STRPTR Prompt,STRPTR Buffer):
*
* Get a string from the user, very much the same as xpr_gets.
*/
BOOL
GetString(BOOL LoadGadget,BOOL Password,LONG MaxChars,STRPTR Prompt,STRPTR Buffer)
{
enum { GAD_OK=1,GAD_CANCEL,GAD_STRING };
struct LayoutHandle *Handle;
UBYTE LocalBuffer[256];
BOOL Success = FALSE;
if(!MaxChars)
MaxChars = sizeof(LocalBuffer) - 1;
if(MaxChars > sizeof(LocalBuffer) - 1)
{
CopyMem(Buffer,LocalBuffer,sizeof(LocalBuffer) - 1);
LocalBuffer[sizeof(LocalBuffer) - 1] = 0;
MaxChars = sizeof(LocalBuffer) - 1;
}
else
strcpy(LocalBuffer,Buffer);
if(!Prompt)
Prompt = LocaleString(MSG_TERMXPR_INPUT_REQUIRED_TXT);
if(Handle = LT_CreateHandleTags(Window->WScreen,
LAHN_LocaleHook, &LocaleHook,
TAG_DONE))
{
struct Window *PanelWindow;
LT_New(Handle,
LA_Type, VERTICAL_KIND,
TAG_DONE);
{
LT_New(Handle,
LA_Type, VERTICAL_KIND,
LA_LabelText, Prompt,
TAG_DONE);
{
if(Password)
{
LT_New(Handle,
LA_Type, PASSWORD_KIND,
LA_STRPTR, LocalBuffer,
LA_ID, GAD_STRING,
LA_Chars, 40,
GTST_MaxChars, MaxChars,
TAG_DONE);
}
else
{
LT_New(Handle,
LA_Type, STRING_KIND,
LA_STRPTR, LocalBuffer,
LA_ID, GAD_STRING,
LA_Chars, 60,
LAST_Picker, LoadGadget,
TAG_DONE);
}
LT_EndGroup(Handle);
}
LT_New(Handle,
LA_Type,VERTICAL_KIND,
TAG_DONE);
{
LT_New(Handle,
LA_Type, XBAR_KIND,
LAXB_FullSize, TRUE,
TAG_DONE);
LT_EndGroup(Handle);
}
LT_New(Handle,LA_Type,HORIZONTAL_KIND,
LAGR_SameSize, TRUE,
LAGR_Spread, TRUE,
TAG_DONE);
{
LT_New(Handle,
LA_Type, BUTTON_KIND,
LA_LabelID, MSG_TERMXPR_OKAY_GAD,
LA_ID, GAD_OK,
LABT_ReturnKey, TRUE,
LABT_ExtraFat, TRUE,
TAG_DONE);
LT_New(Handle,
LA_Type, BUTTON_KIND,
LA_LabelID, MSG_GLOBAL_CANCEL_GAD,
LA_ID, GAD_CANCEL,
LABT_EscKey, TRUE,
LABT_ExtraFat, TRUE,
TAG_DONE);
LT_EndGroup(Handle);
}
}
if(PanelWindow = LT_Build(Handle,
LAWN_TitleID, MSG_GLOBAL_ENTER_TEXT_TXT,
LAWN_HelpHook, &GuideHook,
LAWN_Parent, Window,
WA_DepthGadget, TRUE,
WA_DragBar, TRUE,
WA_RMBTrap, TRUE,
WA_Activate, TRUE,
WA_SimpleRefresh, TRUE,
TAG_DONE))
{
struct IntuiMessage *Message;
BOOL Done = FALSE;
ULONG MsgClass;
UWORD MsgCode;
struct Gadget *MsgGadget;
LT_Activate(Handle,GAD_STRING);
PushWindow(PanelWindow);
LT_ShowWindow(Handle,TRUE);
do
{
if(Wait(PORTMASK(PanelWindow->UserPort) | SIG_BREAK) & SIG_BREAK)
break;
while(Message = (struct IntuiMessage *)LT_GetIMsg(Handle))
{
MsgClass = Message->Class;
MsgCode = Message->Code;
MsgGadget = (struct Gadget *)Message->IAddress;
LT_ReplyIMsg(Message);
if(MsgClass == IDCMP_GADGETUP)
{
switch(MsgGadget->GadgetID)
{
case GAD_STRING:
if(MsgCode == '\r')
{
LT_UpdateStrings(Handle);
strcpy(Buffer,LocalBuffer);
Success = Done = TRUE;
LT_PressButton(Handle,GAD_OK);
}
break;
case GAD_OK:
LT_UpdateStrings(Handle);
strcpy(Buffer,LocalBuffer);
Success = Done = TRUE;
break;
case GAD_CANCEL:
Done = TRUE;
break;
}
}
if(MsgClass == IDCMP_IDCMPUPDATE && MsgGadget->GadgetID == GAD_STRING)
{
UBYTE DummyBuffer[MAX_FILENAME_LENGTH];
struct FileRequester *FileRequest;
strcpy(DummyBuffer,LocalBuffer);
if(FileRequest = OpenSingleFile(PanelWindow,LocaleString(MSG_TERMAUX_LOAD_FILE_TXT),NULL,NULL,DummyBuffer,sizeof(DummyBuffer)))
{
FreeAslRequest(FileRequest);
LT_SetAttributes(Handle,GAD_STRING,
GTST_String, DummyBuffer,
TAG_DONE);
}
}
}
}
while(!Done);
PopWindow();
}
LT_DeleteHandle(Handle);
}
return(Success);
}
/* WakeUp(struct Window *Window,LONG Sound):
*
* Pop a window to the front and alert the user.
*/
VOID
WakeUp(struct Window *Window,LONG Sound)
{
if(Window)
{
if(Config->MiscConfig->AlertMode == ALERT_SCREEN || Config->MiscConfig->AlertMode == ALERT_BEEP_SCREEN)
{
if(Window->WScreen->LeftEdge > 0)
{
if(Window->WScreen->TopEdge > 0)
MoveScreen(Window->WScreen,-Window->WScreen->LeftEdge,-Window->WScreen->TopEdge);
else
MoveScreen(Window->WScreen,-Window->WScreen->LeftEdge,0);
}
else
{
if(Window->WScreen->TopEdge > 0)
MoveScreen(Window->WScreen,0,-Window->WScreen->TopEdge);
}
WindowToFront(Window);
ScreenToFront(Window->WScreen);
}
}
if(Sound != SOUND_BELL || Config->MiscConfig->AlertMode == ALERT_BEEP || Config->MiscConfig->AlertMode == ALERT_BEEP_SCREEN)
SoundPlay(Sound);
}
/* BlockWindows():
*
* Block the main window and the status window (i.e. disable
* the menu and attach a wait pointer).
*/
VOID
BlockWindows()
{
if(!(BlockNestCount++))
{
LT_LockWindow(Window);
LT_LockWindow(StatusWindow);
LT_LockWindow(FastWindow);
LT_LockWindow(MatrixWindow);
WeAreBlocking = TRUE;
SetQueueDiscard(SpecialQueue,TRUE);
GhostCursor();
}
}
/* ReleaseWindows():
*
* Reenable the menus and clear the wait pointer.
*/
VOID
ReleaseWindows()
{
if(BlockNestCount == 1)
{
LT_UnlockWindow(Window);
LT_UnlockWindow(StatusWindow);
LT_UnlockWindow(FastWindow);
LT_UnlockWindow(MatrixWindow);
WeAreBlocking = FALSE;
SetQueueDiscard(SpecialQueue,FALSE);
if(Window)
{
Forbid();
if(Window->Flags & WFLG_WINDOWACTIVE)
NormalCursor();
Permit();
}
}
if(BlockNestCount)
BlockNestCount--;
}
/* LineRead(BPTR File,STRPTR Buffer,LONG MaxChars):
*
* Read a few bytes from a file (à la gets).
*/
LONG
LineRead(BPTR File,STRPTR Buffer,LONG MaxChars)
{
STATIC UBYTE Data[1024];
STATIC LONG ReadIndex,ReadLen;
LONG BytesRead = 0;
if(File)
{
LONG i;
for(i = 0 ; i < MaxChars ; i++)
{
if(ReadIndex >= ReadLen)
{
ReadLen = Read(File,Data,sizeof(Data));
ReadIndex = 0;
if(ReadLen <= 0)
{
Buffer[i] = 0;
break;
}
}
BytesRead++;
if((Buffer[i] = Data[ReadIndex++]) == '\n')
{
Buffer[i + 1] = 0;
break;
}
}
}
else
ReadIndex = ReadLen = 0;
return(BytesRead);
}
/* GetBaudRate(STRPTR Buffer):
*
* Calculate the baud rate contained in a connect string.
*/
LONG
GetBaudRate(STRPTR Buffer)
{
UBYTE LocalBuffer[40];
LONG Rate,i,j;
for(i = j = 0 ; i < strlen(Buffer) ; i++)
{
if(Buffer[i] == ' ')
continue;
else
{
if(Buffer[i] >= '0' && Buffer[i] <= '9')
LocalBuffer[j++] = Buffer[i];
else
break;
}
}
LocalBuffer[j] = 0;
if(StrToLong(LocalBuffer,&Rate) > 0)
{
if(Rate > 0)
return(Rate);
}
return(0);
}
/* GetFileSize(STRPTR Name):
*
* Simple routine to return the size of a file in
* bytes.
*/
LONG
GetFileSize(STRPTR Name)
{
BPTR FileLock;
LONG FileSize = 0;
D_S(struct FileInfoBlock,FileInfo);
if(FileLock = Lock(Name,ACCESS_READ))
{
if(Examine(FileLock,FileInfo))
{
if(FileInfo->fib_DirEntryType < 0)
FileSize = FileInfo->fib_Size;
}
UnLock(FileLock);
}
return(FileSize);
}
/* PutDimensionTags(struct Window *Reference,LONG Left,LONG Top,LONG Width,LONG Height):
*
* Put back the default values for the requesters to open.
*/
VOID
PutDimensionTags(struct Window *Reference,LONG Left,LONG Top,LONG Width,LONG Height)
{
if(Config->MiscConfig->RequesterMode != REQUESTERMODE_IGNORE && (!Config->MiscConfig->RequesterWidth || !Config->MiscConfig->RequesterHeight))
{
if(!Reference)
Reference = Window;
Config->MiscConfig->RequesterLeft = Left - Reference->LeftEdge;
Config->MiscConfig->RequesterTop = Top - Reference->TopEdge;
Config->MiscConfig->RequesterWidth = Width;
Config->MiscConfig->RequesterHeight = Height;
}
}
/* GetDimensionTags(struct Window *Reference,struct TagItem *Tags):
*
* Fills an array of tagitems with the dimensions of an asl requester
* to be opened.
*/
struct TagItem *
GetDimensionTags(struct Window *Reference,struct TagItem *Tags)
{
if(Config->MiscConfig->RequesterMode == REQUESTERMODE_IGNORE || Config->MiscConfig->RequesterWidth < 1 || Config->MiscConfig->RequesterHeight < 1)
{
STATIC ULONG Done = TAG_DONE;
return((struct TagItem *)&Done);
}
else
{
LONG Left,Top,Width,Height;
if(!Reference)
Reference = Window;
if(Config->MiscConfig->RequesterMode == REQUESTERMODE_CENTRE)
{
Left = Reference->LeftEdge + (Reference->Width - Config->MiscConfig->RequesterWidth) / 2;
Top = Reference->TopEdge + (Reference->Height - Config->MiscConfig->RequesterHeight) / 2;
}
else
{
Left = Config->MiscConfig->RequesterLeft + Reference->LeftEdge;
Top = Config->MiscConfig->RequesterTop + Reference->TopEdge;
}
Width = Config->MiscConfig->RequesterWidth;
Height = Config->MiscConfig->RequesterHeight;
Tags[0].ti_Tag = ASL_LeftEdge;
Tags[0].ti_Data = Left;
Tags[1].ti_Tag = ASL_TopEdge;
Tags[1].ti_Data = Top;
Tags[2].ti_Tag = ASL_Width;
Tags[2].ti_Data = Width;
Tags[3].ti_Tag = ASL_Height;
Tags[3].ti_Data = Height;
Tags[4].ti_Tag = TAG_DONE;
return(Tags);
}
}
/* ShowRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...):
*
* Really quite simple varargs version of Intuition's
* EasyRequest requester.
*/
LONG
ShowRequest(struct Window *Window,STRPTR Text,STRPTR Gadgets,...)
{
struct EasyStruct Easy;
va_list VarArgs;
LONG i,GadgetCount;
for(i = GadgetCount = 0 ; i < strlen(Gadgets) ; i++)
{
if(Gadgets[i] == '|')
GadgetCount++;
}
/* Standard data. */
Easy.es_StructSize = sizeof(struct EasyStruct);
Easy.es_Flags = NULL;
Easy.es_Title = LocaleString(MSG_TERMAUX_TERM_REQUEST_TXT);
Easy.es_TextFormat = Text;
Easy.es_GadgetFormat = Gadgets;
if(GadgetCount)
{
LONG Result;
if(GTLayoutBase)
LT_LockWindow(Window);
/* Use the argument array to build the
* requester and display it.
*/
va_start(VarArgs,Gadgets);
Result = EasyRequestArgs(Window,&Easy,NULL,(APTR)VarArgs);
va_end(VarArgs);
if(GTLayoutBase)
LT_UnlockWindow(Window);
return(Result);
}
else
{
struct Window *ReqWindow;
if(GTLayoutBase)
LT_LockWindow(Window);
va_start(VarArgs,Gadgets);
if(ReqWindow = BuildEasyRequestArgs(Window,&Easy,IDCMP_RAWKEY,(APTR)VarArgs))
{
ULONG IDCMP;
LONG Result;
FOREVER
{
WaitPort(ReqWindow->UserPort);
IDCMP = NULL;
Result = SysReqHandler(ReqWindow,&IDCMP,FALSE);
if(!Result || (Result == -2 && !(IDCMP & IDCMP_RAWKEY)))
break;
}
FreeSysRequest(ReqWindow);
}
va_end(VarArgs);
if(GTLayoutBase)
LT_UnlockWindow(Window);
return(0);
}
}
/* CloseWindowSafely(struct Window *Window):
*
* Close a window freeing all messages pending at
* its user port (taken from example source code
* published once upon a time in Amiga Mail).
*/
VOID
CloseWindowSafely(struct Window *Window)
{
Forbid();
if(Window->UserPort)
{
struct Node *Node,*Next;
for(Node = Window->UserPort->mp_MsgList.lh_Head ; Next = Node->ln_Succ ; Node = Next)
{
if(((struct IntuiMessage *)Node)->IDCMPWindow == Window)
{
Remove(Node);
ReplyMsg((struct Message *)Node);
}
}
Window->UserPort = NULL;
}
ModifyIDCMP(Window,NULL);
Permit();
LT_DeleteWindowLock(Window);
CloseWindow(Window);
}
/* DelayTime(LONG Secs,LONG Micros):
*
* Delay for a given period of time.
*/
VOID
DelayTime(LONG Secs,LONG Micros)
{
StopTime();
if(Secs || Micros)
{
StartTime(Secs,Micros);
WaitTime();
}
}
/* WaitTime():
*
* Wait for a pending time request to finish.
*/
VOID
WaitTime()
{
if(TimerRunning)
{
TimerRunning = FALSE;
WaitIO((struct IORequest *)TimeRequest);
}
}
/* StopTime():
*
* Stop the running timer.
*/
VOID
StopTime()
{
if(TimerRunning)
{
if(!CheckIO((struct IORequest *)TimeRequest))
AbortIO((struct IORequest *)TimeRequest);
WaitIO((struct IORequest *)TimeRequest);
}
}
/* StartTime(LONG Secs,LONG Micros):
*
* Start the timer asynchronously.
*/
VOID
StartTime(LONG Secs,LONG Micros)
{
StopTime();
if(Secs || Micros)
{
TimeRequest->tr_node.io_Command = TR_ADDREQUEST;
TimeRequest->tr_time.tv_secs = Secs;
TimeRequest->tr_time.tv_micro = Micros;
ClrSignal(SIG_TIMER);
SendIO((struct IORequest *)TimeRequest);
TimerRunning = TRUE;
}
}
/* GetEnvDOS(STRPTR Name,STRPTR Buffer):
*
* Get the contents of a vanilla AmigaDOS environment
* variable.
*/
BOOL
GetEnvDOS(STRPTR Name,STRPTR Buffer,LONG BufferSize)
{
if(GetVar(Name,Buffer,256,NULL) >= 0)
return(TRUE);
else
{
Buffer[0] = 0;
return(FALSE);
}
}
/* SetEnvDOS(STRPTR Name,STRPTR Value):
*
* Set the contents of a vanilla AmigaDOS environment
* variable.
*/
BOOL
SetEnvDOS(STRPTR Name,STRPTR Value)
{
if(SetVar(Name,Value,-1,GVF_SAVE_VAR))
{
/* Ouch! Bug in dos.library V39! GVF_SAVE_VAR doesn't
* work unless GVF_GLOBAL_ONLY is set as well.
*/
/* if(Kick30)*/
/* return(TRUE);*/
/* else*/
{
UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
BOOL Result = FALSE;
strcpy(LocalBuffer,"ENVARC:");
if(AddPart(LocalBuffer,FilePart(Name),sizeof(LocalBuffer)))
{
BPTR FileHandle;
if(!(FileHandle = Open(LocalBuffer,MODE_NEWFILE)))
Result = FALSE;
else
{
LONG Length = strlen(Value);
if(Write(FileHandle,Value,Length) == Length)
Result = TRUE;
Close(FileHandle);
}
}
return(Result);
}
}
return(FALSE);
}
/* BumpWindow(struct Window *SomeWindow):
*
* Bring a window to the front (and shift the screen
* back to its initial position).
*/
VOID
BumpWindow(struct Window *SomeWindow)
{
if(SomeWindow)
{
if(SomeWindow->WScreen->LeftEdge > 0)
{
if(SomeWindow->WScreen->TopEdge > 0)
MoveScreen(SomeWindow->WScreen,-SomeWindow->WScreen->LeftEdge,-SomeWindow->WScreen->TopEdge);
else
MoveScreen(SomeWindow->WScreen,-SomeWindow->WScreen->LeftEdge,0);
}
else
{
if(SomeWindow->WScreen->TopEdge > 0)
MoveScreen(SomeWindow->WScreen,0,-SomeWindow->WScreen->TopEdge);
}
ScreenToFront(SomeWindow->WScreen);
ActivateWindow(SomeWindow);
}
}
/* PushWindow(struct Window *Window):
*
* Push/PopWindow implement a single lifo window stack
* which always updates the window to activate when
* LSHIFT+RSHIFT+RETURN is pressed. This routine will
* push a window on the stack.
*/
VOID
PushWindow(struct Window *Window)
{
if(WindowStackPtr < 5)
{
WindowStack[WindowStackPtr++] = Window;
TopWindow = Window;
}
}
/* PopWindow():
*
* Remove topmost window from window stack.
*/
VOID
PopWindow()
{
if(WindowStackPtr > 0)
{
WindowStackPtr--;
if(WindowStackPtr)
TopWindow = WindowStack[WindowStackPtr - 1];
else
TopWindow = Window;
}
}
/* SplitFileName():
*
* Split a full file name into a file and a drawer name.
*/
VOID
SplitFileName(STRPTR FullName,STRPTR *FileName,STRPTR DrawerName)
{
if(FilePart(FullName) == FullName)
{
*DrawerName = 0;
*FileName = FullName;
}
else
{
STRPTR Dummy;
strcpy(DrawerName,FullName);
Dummy = PathPart(DrawerName);
*Dummy = 0;
*FileName = FilePart(FullName);
}
}
/* BackfillRoutine():
*
* Window layer backfill routine.
*/
VOID SAVE_DS ASM
BackfillRoutine(REG(a0) struct Hook *UnusedHook,REG(a2) struct RastPort *RPort,REG(a1) LayerMsg *Bounds)
{
struct RastPort RastPort;
CopyMem(RPort,&RastPort,sizeof(struct RastPort));
RastPort.Layer = NULL;
RPort = &RastPort;
SetAPen(RPort,Pens[BACKGROUNDPEN]);
SetDrMd(RPort,JAM2);
RectFill(RPort,Bounds->Bounds.MinX,Bounds->Bounds.MinY,Bounds->Bounds.MaxX,Bounds->Bounds.MaxY);
}
struct NameSegment
{
UBYTE String[63],
Separator;
};
STATIC STRPTR
FindChar(STRPTR Template,LONG c)
{
while(*Template)
{
if(*Template == c)
return(Template);
else
Template++;
}
return(NULL);
}
STATIC UBYTE *
GetNameSegment(struct NameSegment *NameSegment,UBYTE *cp,LONG i)
{
UBYTE *xp = NameSegment[i].String;
while (*cp && !FindChar("._+-,@~=",*cp))
*xp++ = *cp++;
*xp = '\0';
NameSegment[i].Separator = *cp;
if (*cp)
cp++;
if(NameSegment[i].String[0] || NameSegment[i].Separator)
return(cp);
else
return(NULL);
}
STATIC VOID
CopyNameSegment(struct NameSegment *NameSegment,UBYTE *Destination,LONG Zap)
{
UBYTE *cp = Destination,*xp;
for(xp = NameSegment[0].String ; *xp ; )
*cp++ = *xp++;
if(NameSegment[0].Separator)
{
LONG i;
*cp++ = NameSegment[0].Separator;
for(i = Zap + 1 ; ; i++)
{
for(xp = NameSegment[i].String ; *xp ; )
*cp++ = *xp++;
if(NameSegment[i].Separator)
*cp++ = NameSegment[i].Separator;
else
{
if(!NameSegment[i].String[0])
break;
}
}
}
*cp = 0;
}
/* ShrinkName():
*
* Shrink a file name down to a number of characters, if
* possible preserving the structure of the name. Algorithm
* courtesy of the "shrink" program by Simon Brown,
* Edinburgh University.
*/
UBYTE *
ShrinkName(UBYTE *Source,UBYTE *Destination,LONG MaxLength,BOOL FixSuffix)
{
#define MAXSEGS 10
struct NameSegment NameSegment[MAXSEGS];
LONG i,NumSegments,SuffixLength,Remainder,Delete,Total,Zap = 0;
UBYTE *OldPtr = (UBYTE *)Source;
for(i = 0 ; i < MAXSEGS && (OldPtr = GetNameSegment(NameSegment,OldPtr,i)) ; i++);
if(i < MAXSEGS)
{
NumSegments = i - 1;
if((NumSegments * 2) < MaxLength)
{
SuffixLength = strlen(NameSegment[NumSegments].String);
if(SuffixLength > MaxLength - NumSegments - 1)
{
SuffixLength = MaxLength - (2 * NumSegments) - 1;
NameSegment[NumSegments].String[SuffixLength - 1] = 0;
}
else
{
if (SuffixLength + NumSegments > MaxLength-NumSegments-1)
Zap = NumSegments - (MaxLength-SuffixLength)/2;
}
if(NumSegments >= 1)
{
for(i = Zap + 1 ; i <= NumSegments ; i++)
{
if(NameSegment[i].Separator)
SuffixLength++;
}
if(NameSegment[0].Separator)
SuffixLength++;
Remainder = MaxLength - SuffixLength;
Delete = Remainder / NumSegments;
Total = SuffixLength;
for(i = Zap + 1 ; i < NumSegments ; i++)
{
NameSegment[i].String[Delete] = 0;
Total += Delete;
}
NameSegment[0].String[MaxLength - Total] = 0;
}
CopyNameSegment(NameSegment,Destination,Zap);
}
else
strcpy(Destination,Source);
}
else
strcpy(Destination,Source);
if(FixSuffix)
{
BOOL GotDot = FALSE;
LONG Len = strlen(Destination),Dots;
for(i = Dots = 0 ; i < Len ; i++)
{
if(Destination[i] == '.')
Dots++;
}
if(!Dots)
{
if(Len < 4)
strcat(Destination,".___");
else
Destination[Len - 4] = '.';
}
for(i = Len - 1 ; i >= 0 ; i--)
{
if(Destination[i] == '.')
{
if(GotDot)
Destination[i] = '_';
else
GotDot = TRUE;
}
if(Destination[i] == '\\')
Destination[i] = '-';
}
}
return(Destination);
}
/* BuildFontName(STRPTR Destination,STRPTR Name,LONG Size):
*
* Build a font name and size string from given
* information (raw name and size).
*/
VOID
BuildFontName(STRPTR Destination,LONG DestinationSize,STRPTR Name,LONG Size)
{
UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
LONG Len;
Name = FilePart(Name);
Len = strlen(Name);
if(Len > 5 && !Stricmp(&Name[Len - 5],".font"))
{
strcpy(LocalBuffer,Name);
LocalBuffer[Len - 5] = 0;
Name = LocalBuffer;
}
LimitedSPrintf(DestinationSize,Destination,"%s %ld",Name,Size);
}
/* FixName(STRPTR Name):
*
* Build a correct AmigaDOS filename.
*/
VOID
FixName(STRPTR Name)
{
LONG NameLen = strlen(Name),i;
/* Replace special characters. */
for(i = 0 ; i < NameLen ; i++)
{
switch(Name[i])
{
case ' ':
Name[i] = '_';
break;
case ':':
Name[i] = '.';
break;
case '/':
Name[i] = '\\';
break;
case '\"':
Name[i] = '\'';
break;
}
}
/* Truncate the name. */
if(NameLen > 31)
Name[31] = 0;
}
/* ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String):
*
* Display an error message, in human readable form if possible.
*/
VOID
ShowError(struct Window *Window,LONG Primary,LONG Secondary,STRPTR String)
{
STATIC LONG LocalErrors[][2] =
{
ERR_SAVE_ERROR, MSG_ERR_COULD_NOT_SAVE_FILE_TXT,
ERR_LOAD_ERROR, MSG_ERR_COULD_NOT_LOAD_FILE_TXT,
ERR_OUTDATED, MSG_ERR_OUTDATED_TXT,
ERR_EXECUTE_ERROR, MSG_ERR_COULD_NOT_EXECUTE_PROGRAM_TXT,
ERR_FILE_NOT_FOUND, MSG_VERIFY_NO_FILE_TXT,
ERR_DRAWER_NOT_FOUND, MSG_VERIFY_DRAWER_NOT_FOUND_TXT,
ERR_PROGRAM_NOT_FOUND, MSG_VERIFY_NO_PROGRAM_TXT,
ERR_NOT_A_FILE, MSG_VERIFY_DRAWER_NOT_A_FILE_TXT,
ERR_NOT_A_DRAWER, MSG_VERIFY_FILE_NOT_A_DRAWER_TXT,
IFFERR_NOMEM, MSG_IFFERR_NOMEM_TXT,
IFFERR_READ, MSG_IFFERR_READ_TXT,
IFFERR_WRITE, MSG_IFFERR_WRITE_TXT,
IFFERR_SEEK, MSG_IFFERR_SEEK_TXT,
IFFERR_MANGLED, MSG_IFFERR_MANGLED_TXT,
IFFERR_NOTIFF, MSG_IFFERR_NOTIFF_TXT,
0
};
UBYTE LocalBuffer1[FAULT_MAX],LocalBuffer2[FAULT_MAX];
STRPTR PrimaryError,SecondaryError;
PrimaryError = SecondaryError = NULL;
if(Primary)
{
LONG i;
for(i = 0 ; LocalErrors[i][0] ; i++)
{
if(LocalErrors[i][0] == Primary)
{
PrimaryError = LocaleString(LocalErrors[i][1]);
break;
}
}
if(!PrimaryError)
{
if(Fault(Primary,NULL,LocalBuffer1,sizeof(LocalBuffer1)))
PrimaryError = LocalBuffer1;
}
}
if(Secondary)
{
LONG i;
for(i = 0 ; LocalErrors[i][0] ; i++)
{
if(LocalErrors[i][0] == Secondary)
{
SecondaryError = LocaleString(LocalErrors[i][1]);
break;
}
}
if(!SecondaryError)
{
if(Fault(Secondary,NULL,LocalBuffer2,sizeof(LocalBuffer2)))
SecondaryError = LocalBuffer2;
}
}
if(PrimaryError)
{
if(String)
ShowRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),String,SecondaryError);
else
ShowRequest(Window,PrimaryError,LocaleString(MSG_GLOBAL_CONTINUE_TXT),SecondaryError);
}
}
struct List *
BuildModeList(LONG *Index,ULONG DisplayMode,MODEFILTER ModeFilter,APTR UserData)
{
struct List *List;
LONG Count = 0;
*Index = 0;
if(List = CreateList())
{
struct DisplayInfo DisplayInfo;
ULONG SomeMode = INVALID_ID;
while((SomeMode = NextDisplayInfo(SomeMode)) != INVALID_ID)
{
if(GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(struct DisplayInfo),DTAG_DISP,SomeMode))
{
if((DisplayInfo.PropertyFlags & DIPF_IS_WB) && !(DisplayInfo.NotAvailable & ~DI_AVAIL_NOTWITHGENLOCK))
{
UBYTE ModeNameBuffer[DISPLAYNAMELEN + 1];
struct ModeNode *ModeNode;
if(ModeFilter)
{
if(!(*ModeFilter)(SomeMode,UserData))
continue;
}
GetModeName(SomeMode,ModeNameBuffer,sizeof(ModeNameBuffer));
if(ModeNode = (struct ModeNode *)AllocVecPooled(sizeof(struct ModeNode) + strlen(ModeNameBuffer) + 1,MEMF_ANY))
{
strcpy(ModeNode->Node.ln_Name = (STRPTR)(ModeNode + 1),ModeNameBuffer);
ModeNode->DisplayID = SomeMode;
AddTail(List,(struct Node *)ModeNode);
Count++;
}
}
}
}
}
if(Count)
{
struct ModeNode *Node,*Next;
for(Node = (struct ModeNode *)List->lh_Head ; Node->Node.ln_Succ ; Node = (struct ModeNode *)Node->Node.ln_Succ)
{
if(!(Node->DisplayID & MONITOR_ID_MASK))
{
for(Next = (struct ModeNode *)List->lh_Head ; Next->Node.ln_Succ ; Next = (struct ModeNode *)Next->Node.ln_Succ)
{
if((Node->DisplayID & ~MONITOR_ID_MASK) == (Next->DisplayID & ~MONITOR_ID_MASK) && Next != Node)
Node->DisplayID = INVALID_ID;
}
}
for(Next = (struct ModeNode *)List->lh_Head ; Next->Node.ln_Succ ; Next = (struct ModeNode *)Next->Node.ln_Succ)
{
if(Node->DisplayID == Next->DisplayID && Next != Node)
Next->DisplayID = INVALID_ID;
}
}
for(Node = (struct ModeNode *)List->lh_Head ; Next = (struct ModeNode *)Node->Node.ln_Succ ; Node = Next)
{
if(Node->DisplayID == INVALID_ID)
{
Count--;
Remove((struct Node *)Node);
FreeVecPooled(Node);
}
}
}
if(Count)
{
struct ModeNode *Node,*Next;
for(Count = 0, Node = (struct ModeNode *)List->lh_Head ; Next = (struct ModeNode *)Node->Node.ln_Succ ; Node = Next)
{
if(Node->DisplayID == DisplayMode)
{
*Index = Count;
break;
}
}
return(List);
}
else
{
DeleteList(List);
return(NULL);
}
}
/* IsAssign(STRPTR Name):
*
* Does a name refer to an assignment?
*/
BOOL
IsAssign(STRPTR Name)
{
LONG NameLen = strlen(Name) - 1;
BOOL Result = FALSE;
/* Does it end with a colon? */
if(Name[NameLen] == ':')
{
struct DosList *DosList;
STRPTR AssignName;
/* Lock the list of assignments for reading. */
DosList = LockDosList(LDF_ASSIGNS | LDF_READ);
/* Scan the list... */
while(DosList = NextDosEntry(DosList,LDF_ASSIGNS))
{
/* Convert the name from icky
* BCPL to `C' style string.
*/
AssignName = (STRPTR)BADDR(DosList->dol_Name);
/* Does the name length match? */
if(AssignName[0] == NameLen)
{
/* Does the name itself match? */
if(!Strnicmp(&AssignName[1],Name,NameLen))
{
Result = TRUE;
break;
}
}
}
/* Unlock the list of assignments. */
UnLockDosList(LDF_ASSIGNS | LDF_READ);
}
/* Return the result. */
return(Result);
}
/* LockInAssign(BPTR TheLock,STRPTR TheAssignment):
*
* Check if a file lock is part of an assignment.
*/
BOOL
LockInAssign(BPTR TheLock,STRPTR TheAssignment)
{
struct DevProc *DevProc = NULL;
struct MsgPort *FileSysTask = GetFileSysTask();
BOOL Result = FALSE;
/* Loop until all assignments are
* processed.
*/
do
{
/* Get the default filesystem task
* in case we stumble upon NULL
* directory locks.
*/
if(DevProc = GetDeviceProc(TheAssignment,DevProc))
{
/* Set the default filesystem task. */
SetFileSysTask(DevProc->dvp_Port);
/* Is the lock on the list? */
if(SameLock(DevProc->dvp_Lock,TheLock) == LOCK_SAME)
Result = TRUE;
}
else
break;
}
while(DevProc && (DevProc->dvp_Flags & DVPF_ASSIGN) && !Result);
/* Reset the default filesystem task. */
SetFileSysTask(FileSysTask);
/* Free device process data. */
if(DevProc)
FreeDeviceProc(DevProc);
return(Result);
}
/* DeleteBitMap(struct BitMap *BitMap):
*
* Delete a bitmap created by CreateBitMap().
*/
VOID
DeleteBitMap(struct BitMap *BitMap)
{
if(BitMap)
{
WaitBlit();
if(Kick30)
FreeBitMap(BitMap);
else
{
LONG i,*Sizes,Width,Height;
Sizes = &((LONG *)BitMap)[-2];
Width = Sizes[0];
Height = Sizes[1];
for(i = 0 ; i < BitMap->Depth ; i++)
FreeRaster(BitMap->Planes[i],Width,Height);
FreeVecPooled(Sizes);
}
}
}
/* CreateBitMap(ULONG Width,ULONG Height,ULONG Depth,ULONG Flags,struct BitMap *Friend):
*
* Create a new bitmap with given properties.
*/
struct BitMap *
CreateBitMap(ULONG Width,ULONG Height,ULONG Depth,ULONG Flags,struct BitMap *Friend)
{
if(Kick30)
return(AllocBitMap(Width,Height,Depth,Flags,Friend));
else
{
struct BitMap *BitMap;
LONG Plus;
LONG *Sizes;
if(Depth > 8)
Plus = (Depth - 8) * sizeof(PLANEPTR);
else
Plus = 0;
if(!(Sizes = (LONG *)AllocVecPooled(sizeof(LONG) * 2 + sizeof(struct BitMap) + Plus,MEMF_CLEAR)))
BitMap = NULL;
else
{
LONG i;
BitMap = (struct BitMap *)&Sizes[2];
InitBitMap(BitMap,Depth,Width,Height);
for(i = 0 ; i < BitMap->Depth ; i++)
{
if(!(BitMap->Planes[i] = AllocRaster(Width,Height)))
{
LONG j;
for(j = 0 ; j < i ; j++)
FreeRaster(BitMap->Planes[j],Width,Height);
FreeVecPooled(Sizes);
return(NULL);
}
}
if(Flags & BMF_CLEAR)
BltBitMap(BitMap,0,0,BitMap,0,0,Width,Height,0x00,(1 << Depth) - 1,NULL);
Sizes[0] = Width;
Sizes[1] = Height;
}
return(BitMap);
}
}
/* LaunchWorkCommon(LaunchMsg *Startup,BOOL Synchronous):
*
* Does the final launch & cleanup work with the
* startup packed provided.
*/
STATIC BOOL
LaunchWorkCommon(LaunchMsg *Startup,BOOL Synchronous)
{
/* Did we succeed in creating the startup message? */
if(Startup)
{
LONG Result;
/* Launch the program. */
Result = LaunchSomething(Config->MiscConfig->SuppressOutput ? (STRPTR)"NIL:" : Config->MiscConfig->WindowName,Synchronous,Startup);
/* And return the result. */
return((BOOL)(Result == 0));
}
else
return(FALSE);
}
/* RexxLaunchCleanup(LaunchMsg *Startup):
*
* Displays an error message for the ARexx script
* to be launched.
*/
STATIC VOID
LaunchRexxCleanup(LaunchMsg *Startup)
{
if(Startup->Result != 0)
Printf(LocaleString(MSG_TERMAUX_COMMAND_HAS_TERMINATED_TXT),Startup->Command,Startup->Result,Startup->Result2);
}
/* LaunchRexxCommon(STRPTR Command):
*
* Launch an ARexx command. This routine is always
* asynchronous.
*/
BOOL
LaunchRexxAsync(STRPTR Command)
{
LaunchMsg *Startup;
/* Skip leading blanks. */
while(*Command == ' ' || *Command == '\t')
Command++;
/* Create the launch startup message. This will copy the
* command string.
*/
Startup = CreateRexxCmdLaunchMsg(Command,NULL,LaunchRexxCleanup);
/* Do the work. */
return((BOOL)(LaunchWorkCommon(Startup,FALSE)));
}
/* LaunchCommandCommon(STRPTR Command, BOOL Synchronous):
*
* Launch a command, try to figure out if it's an ARexx
* command, a plain batch file or a program and act
* accordingly.
*/
STATIC BOOL
LaunchCommandCommon(STRPTR Command, BOOL Synchronous)
{
STRPTR OriginalCommand;
UBYTE NameBuffer[MAX_FILENAME_LENGTH];
BOOL IsScript;
BPTR CommandFile;
BPTR FileLock;
LONG i;
LaunchMsg *Startup;
/* Chop off the arguments. */
while(*Command == ' ' || *Command == '\t')
Command++;
OriginalCommand = Command;
CopyMem(Command,NameBuffer,sizeof(NameBuffer) - 1);
NameBuffer[sizeof(NameBuffer) - 1] = 0;
for(i = 0 ; i < sizeof(NameBuffer) ; i++)
{
if(NameBuffer[i] == ' ' || NameBuffer[i] == '\t')
{
NameBuffer[i] = 0;
break;
}
}
/* Now do something useful. Check if the command
* could be an ARexx script.
*/
if(CommandFile = Open(NameBuffer,MODE_OLDFILE))
{
UBYTE LocalBuffer[MAX_FILENAME_LENGTH];
BOOL IsRexx = FALSE;
LONG Len;
/* 256 bytes may be not be enough, but then
* we're only guessing.
*/
if((Len = Read(CommandFile,LocalBuffer,sizeof(LocalBuffer))) > 0)
{
UBYTE c;
for(i = 0 ; i < Len - 1 ; i++)
{
c = LocalBuffer[i];
/* Stop on invalid characters. */
if((c < ' ' && c != '\r' && c != '\n' && c != '\a') || (c >= 127 && c < 160))
break;
else
{
/* Looks like the typical
* introductory comment line.
*/
if(c == '/' && LocalBuffer[i + 1] == '*')
{
IsRexx = TRUE;
break;
}
}
}
}
Close(CommandFile);
/* If it's a Rexx script, launch it. */
if(IsRexx)
return(LaunchRexxAsync(Command));
}
/* Ok, second check. Does it have the script bit set? */
IsScript = FALSE;
if(FileLock = Lock(NameBuffer,ACCESS_READ))
{
D_S(struct FileInfoBlock,FileInfo);
if(Examine(FileLock,FileInfo))
{
if(FileInfo->fib_Protection & FIBF_SCRIPT)
IsScript = TRUE;
}
UnLock(FileLock);
}
/* If it's a script command, prepend the "Execute " command. */
if(IsScript)
{
/* Make room for the new command. */
if(!(Command = AllocVecPooled(strlen("Execute ") + strlen(OriginalCommand) + 1,MEMF_ANY)))
return(FALSE);
else
{
strcpy(Command,"Execute ");
strcat(Command,OriginalCommand);
}
}
/* Create the launch startup message. This will copy the
* command string.
*/
Startup = CreateProgramLaunchMsg(Command,NULL);
/* If we had to make a copy of the command name, release the memory. */
if(Command != OriginalCommand)
FreeVecPooled(Command);
/* Do the work. */
return((BOOL)(LaunchWorkCommon(Startup,Synchronous)));
}
/* LaunchCommand(STRPTR Command):
*
* Launches a command, synchronous version.
*/
BOOL
LaunchCommand(STRPTR Command)
{
return(LaunchCommandCommon(Command,TRUE));
}
/* LaunchCommandAsync(STRPTR Command):
*
* Launches a command, asynchronous version.
*/
BOOL
LaunchCommandAsync(STRPTR Command)
{
return(LaunchCommandCommon(Command,FALSE));
}
/* LaunchProcess(STRPTR Name,VOID (*Entry)(VOID),BPTR Stream):
*
* Launch a new process from given entry point, with given
* name and I/O stream.
*/
struct Process *
LaunchProcess(STRPTR Name,VOID (*Entry)(VOID),BPTR Stream)
{
struct MsgPort *ConsoleTask;
if(Stream && GoodStream(Stream))
ConsoleTask = ((struct FileHandle *)BADDR(Stream))->fh_Type;
else
ConsoleTask = NULL;
return(CreateNewProcTags(
NP_Entry, Entry,
NP_StackSize, 8000,
NP_Name, Name,
NP_Cli, TRUE,
NP_ConsoleTask, ConsoleTask,
ConsoleTask ? TAG_IGNORE : TAG_DONE,0,
NP_Output, ConsoleTask ? NULL : Stream,
ConsoleTask ? NP_Input : TAG_IGNORE,Stream,
TAG_DONE));
}
/* String2Boolean(STRPTR String):
*
* Compare string contents with table contents,
* map the string to a boolean value.
*/
BOOL
String2Boolean(STRPTR String)
{
STATIC STRPTR TrueOptions[] =
{
"ON",
"TRUE",
"T",
"YES",
"Y",
"1"
};
LONG i;
for(i = 0 ; i < NUM_ELEMENTS(TrueOptions) ; i++)
{
if(!Stricmp(String,TrueOptions[i]))
return(TRUE);
}
return(FALSE);
}
/* SendMessageGetReply(struct MsgPort *Port,struct Message *Message):
*
* Send a message to a given MsgPort and wait for
* the reply.
*/
VOID
SendMessageGetReply(struct MsgPort *Port,struct Message *Message)
{
struct MsgPort LocalPort;
struct MsgPort *ReplyPort;
ReplyPort = Message->mn_ReplyPort;
InitSinglePort(&LocalPort);
Message->mn_ReplyPort = &LocalPort;
SetSignal(0,SIGF_SINGLE);
PutMsg(Port,Message);
WaitPort(&LocalPort);
GetMsg(&LocalPort);
Message->mn_ReplyPort = ReplyPort;
}
/* SetOnlineState(BOOL IsOnline):
*
* Set the current online state.
*/
VOID
SetOnlineState(BOOL IsOnline)
{
ObtainSemaphore(&OnlineSemaphore);
WasOnline = Online;
Online = IsOnline;
if(WasOnline && !Online)
ActivateJob(MainJobQueue,OnlineCleanupJob);
ReleaseSemaphore(&OnlineSemaphore);
}
/* SwapMem(APTR FromPtr,APTR ToPtr,LONG Size):
*
* Exchange the contents of two memory regions.
*/
VOID
SwapMem(APTR FromPtr,APTR ToPtr,LONG Size)
{
UBYTE *From,*To,c;
From = FromPtr;
To = ToPtr;
while(Size--)
{
c = *From;
*From++ = *To;
*To++ = c;
}
}
/* CloseIFFClip(struct IFFHandle *Handle):
*
* Closes the clipboard opened by OpenIFFClip.
*/
BOOL
CloseIFFClip(struct IFFHandle *Handle)
{
if(Handle)
{
CloseIFF(Handle);
CloseClipboard((struct ClipboardHandle *)Handle->iff_Stream);
FreeIFF(Handle);
}
return(TRUE);
}
/* OpenIFFClip(LONG Unit,LONG Mode):
*
* Open the clipboard for reading or writing. This
* routine handles all the initizalizations and
* allocation and returns an IFFHandle ready
* to be used.
*/
struct IFFHandle *
OpenIFFClip(LONG Unit,LONG Mode)
{
struct IFFHandle *Handle;
LONG Error;
if(Handle = AllocIFF())
{
if(Handle->iff_Stream = (ULONG)OpenClipboard(Unit))
{
InitIFFasClip(Handle);
if(!(Error = OpenIFF(Handle,(Mode == MODE_NEWFILE) ? IFFF_WRITE : IFFF_READ)))
return(Handle);
CloseClipboard((struct ClipboardHandle *)Handle->iff_Stream);
}
else
Error = ERROR_NO_FREE_STORE;
FreeIFF(Handle);
}
else
Error = ERROR_NO_FREE_STORE;
SetIoErr(Error);
return(FALSE);
}
/* CloseIFFStream(struct IFFHandle *Handle):
*
* Closes an IFF file opened by OpenIFFStream.
*/
BOOL
CloseIFFStream(struct IFFHandle *Handle)
{
if(Handle)
{
BOOL Result;
CloseIFF(Handle);
Result = Close(Handle->iff_Stream);
FreeIFF(Handle);
return(Result);
}
else
return(TRUE);
}
/* OpenIFFStream(STRPTR Name,LONG Mode):
*
* Open an IFF file for reading or writing. This
* routine handles all the initizalizations and
* allocation and returns an IFFHandle ready
* to be used.
*/
struct IFFHandle *
OpenIFFStream(STRPTR Name,LONG Mode)
{
struct IFFHandle *Handle;
LONG Error;
if(Handle = AllocIFF())
{
if(Handle->iff_Stream = Open(Name,Mode))
{
InitIFFasDOS(Handle);
if(!(Error = OpenIFF(Handle,(Mode == MODE_NEWFILE) ? IFFF_WRITE : IFFF_READ)))
return(Handle);
Close(Handle->iff_Stream);
if(Mode == MODE_NEWFILE)
DeleteFile(Name);
}
else
Error = IoErr();
FreeIFF(Handle);
}
else
Error = ERROR_NO_FREE_STORE;
SetIoErr(Error);
return(FALSE);
}
/* InitHook(struct Hook *Hook,HOOKFUNC Func,APTR Data):
*
* Set up a callback hook function.
*/
VOID
InitHook(struct Hook *Hook,HOOKFUNC Func,APTR Data)
{
#ifdef USE_GLUE
Hook->h_Entry = HookEntry;
Hook->h_SubEntry = Func;
Hook->h_Data = Data;
#else
Hook->h_Entry = Func;
Hook->h_Data = Data;
#endif /* USE_GLUE */
}
/* FitText(struct RastPort *RPort,UWORD Width,STRPTR String,LONG Len):
*
* Check how many character fit into Width pixels.
*/
ULONG
FitText(struct RastPort *RPort,UWORD Width,STRPTR String,LONG Len)
{
struct TextExtent Extent;
if(Len == -1)
Len = strlen(String);
return(TextFit(RPort,String,Len,&Extent,NULL,1,Width,32767));
}
/* DispatchRexxDialMsgList(BOOL Ok):
*
* Dispatch all queued dial requests.
*/
VOID
DispatchRexxDialMsgList(BOOL Ok)
{
struct RexxMsg *DialMsg;
LONG Result;
if(Ok)
Result = RC_OK;
else
Result = RC_WARN;
while(DialMsg = (struct RexxMsg *)RemHead(&RexxDialMsgList))
{
DialMsg->rm_Result1 = Result;
DialMsg->rm_Result2 = 0;
ReplyMsg((struct Message *)DialMsg);
}
}
/* CancelZModem():
*
* Send the zmodem cancel sequence.
*/
VOID
CancelZModem()
{
if(UsesZModem)
DoSerialWrite(ZModemCancel,20);
}
/* WaitForHandshake():
*
* Clears the handshaking signal, then waits for it.
* Must be called while in Forbid().
*/
VOID
WaitForHandshake()
{
SetSignal(0,SIG_HANDSHAKE);
Wait(SIG_HANDSHAKE);
}
/* ShakeHands(struct Task *Notify,ULONG NotifyMask):
*
* Send a signal to a Task and wait for it to
* reply with the handshake signal.
*/
VOID
ShakeHands(struct Task *Notify,ULONG NotifyMask)
{
if(Notify)
{
Forbid();
Signal(Notify,NotifyMask);
WaitForHandshake();
Permit();
}
}
/* GetViewPortExtra(struct ViewPort *ViewPort):
*
* Gets the extra information associated with a viewport.
*/
struct ViewPortExtra *
GetViewPortExtra(struct ViewPort *ViewPort)
{
struct TagItem Tags[2] = { VTAG_VIEWPORTEXTRA_GET, NULL, TAG_DONE };
if(!VideoControl(ViewPort->ColorMap,Tags))
return((struct ViewPortExtra *)Tags[0].ti_Data);
else
return(NULL);
}
/* OpenToAppend(STRPTR Name,BOOL *Created):
*
* Open a plain AmigaDOS file to append data to it. If a new file
* is created this routine will indicate this by setting the
* boolean variable pointed to by "Created" to TRUE.
*/
BPTR
OpenToAppend(STRPTR Name,BOOL *Created)
{
BPTR FileHandle;
BPTR FileLock;
if(FileLock = Lock(Name,EXCLUSIVE_LOCK))
{
if(!(FileHandle = OpenFromLock(FileLock)))
{
UnLock(FileLock);
FileHandle = Open(Name,MODE_READWRITE);
}
if(FileHandle)
{
if(Seek(FileHandle,0,OFFSET_END) == -1)
{
LONG Error;
Error = IoErr();
Close(FileHandle);
SetIoErr(Error);
return(NULL);
}
}
if(Created)
*Created = FALSE;
}
else
{
if(FileHandle = Open(Name,MODE_NEWFILE))
{
if(Created)
*Created = TRUE;
}
}
return(FileHandle);
}
/* PushStatus(WORD NewStatus):
*
* Remember the current status and set the new one.
*/
VOID
PushStatus(WORD NewStatus)
{
ObtainSemaphore(&StatusSemaphore);
if(StatusStackPointer < 10)
StatusStack[StatusStackPointer++] = NewStatus;
ReleaseSemaphore(&StatusSemaphore);
}
/* PopStatus():
*
* Return to the old status value.
*/
VOID
PopStatus()
{
ObtainSemaphore(&StatusSemaphore);
if(StatusStackPointer > 0)
StatusStackPointer--;
ReleaseSemaphore(&StatusSemaphore);
}
/* GetStatus():
*
* Returns the current status.
*/
WORD
GetStatus()
{
WORD Status;
SafeObtainSemaphoreShared(&StatusSemaphore);
if(StatusStackPointer > 0)
Status = StatusStack[StatusStackPointer - 1];
else
Status = STATUS_READY;
ReleaseSemaphore(&StatusSemaphore);
if(Status == STATUS_READY && Get_xOFF())
Status = STATUS_HOLDING;
return(Status);
}
/* Clear_xOFF():
*
* Clears the xOFF stop marker.
*/
VOID
Clear_xOFF()
{
ObtainSemaphore(&xONxOFF_Semaphore);
xOFF_Enabled = FALSE;
UpdateSerialJob();
ReleaseSemaphore(&xONxOFF_Semaphore);
}
/* Set_xOFF():
*
* Sets the xOFF stop marker unless access to the
* marker is forbidden.
*/
VOID
Set_xOFF()
{
ObtainSemaphore(&xONxOFF_Semaphore);
if(xONxOFF_Lock == 0)
xOFF_Enabled = TRUE;
UpdateSerialJob();
ReleaseSemaphore(&xONxOFF_Semaphore);
}
/* Get_xOFF():
*
* Queries the current state of the xOFF marker.
*/
BOOL
Get_xOFF()
{
BOOL Result;
SafeObtainSemaphoreShared(&xONxOFF_Semaphore);
Result = xOFF_Enabled;
ReleaseSemaphore(&xONxOFF_Semaphore);
return(Result);
}
/* Lock_xOFF():
*
* Locks the current xOFF marker state.
*/
VOID
Lock_xOFF()
{
ObtainSemaphore(&xONxOFF_Semaphore);
xONxOFF_Lock++;
ReleaseSemaphore(&xONxOFF_Semaphore);
}
/* Unlock_xOFF():
*
* Unlocks the current xOFF marker state.
*/
VOID
Unlock_xOFF()
{
ObtainSemaphore(&xONxOFF_Semaphore);
if(xONxOFF_Lock > 0)
xONxOFF_Lock--;
ReleaseSemaphore(&xONxOFF_Semaphore);
}
/* MoveListViewNode():
*
* Move the node of a list view somewhere.
*/
VOID
MoveListViewNode(LayoutHandle *Handle,struct List *List,LONG ListID,struct Node *Node,LONG *Offset,LONG How)
{
LT_SetAttributes(Handle,ListID,
GTLV_Labels, ~0,
TAG_DONE);
MoveNode(List,Node,How);
*Offset = GetNodeOffset(Node,List);
LT_SetAttributes(Handle,ListID,
GTLV_Labels, List,
LALV_Selected, *Offset,
TAG_DONE);
}
/* StartProcessWaitForHandshake():
*
* Create a new process and wait for the handshake
* signal.
*/
struct Process *
StartProcessWaitForHandshake(STRPTR Name,TASKENTRY Entry,...)
{
struct Process *Process;
va_list Args;
va_start(Args,Entry);
Forbid();
if(Process = CreateNewProcTags(
NP_Name, Name,
NP_Entry, Entry,
TAG_MORE,Args))
WaitForHandshake();
Permit();
va_end(Args);
return(Process);
}
/* LocalGetCurrentDirName(STRPTR Buffer,LONG BufferSize):
*
* Obtains the name of the "current" directory of the
* calling process, regardless of the current directory
* of the Shell environment the process may be running in.
*/
BOOL
LocalGetCurrentDirName(STRPTR Buffer,LONG BufferSize)
{
return((BOOL)NameFromLock(((struct Process *)FindTask(NULL))->pr_CurrentDir,Buffer,BufferSize));
}
/* SafeObtainSemaphoreShared():
*
* This is for backwards compatibility with Kickstart 2.04 and
* avoids a deadlock when trying to get a shared lock on
* a semaphore already held in exclusive mode by the same Task.
*/
VOID
SafeObtainSemaphoreShared(struct SignalSemaphore *Semaphore)
{
/* Do it right with Kickstart 3.x. */
if(Kick30)
ObtainSemaphoreShared(Semaphore);
else
{
/* Try to get the shared semaphore */
if(!AttemptSemaphoreShared(Semaphore))
{
/* Check if we can get the exclusive version */
if(!AttemptSemaphore(Semaphore))
{
/* Oh well, wait for the shared lock */
ObtainSemaphoreShared(Semaphore);
}
}
}
}
/* LocalCreateTask(STRPTR Name,BYTE Priority,TASKENTRY Entry,ULONG StackSize,LONG NumArgs,...):
*
* Special version of CreateTask() that allows for arguments to be passed to
* the Task to be created.
*/
struct Task *
LocalCreateTask(STRPTR Name,LONG Priority,TASKENTRY Entry,ULONG StackSize,LONG NumArgs,...)
{
/* A MemList with an additional MemEntry following it. */
struct FatMemList
{
struct MemList MemList;
struct MemEntry MemEntry;
};
struct MemList *LocalMemList,*MemList;
struct FatMemList FatMemList;
struct Task *Task;
/* Limit the Task priority to legal values. */
if(Priority < -128)
Priority = -128;
else
{
if(Priority > 127)
Priority = 127;
}
/* Clear the result. */
Task = NULL;
/* Round the stack size to a multiple of four. */
StackSize = (StackSize + 3) & ~3;
/* Reset the contents of the local memory allocation request. */
memset(&FatMemList,0,sizeof(FatMemList));
LocalMemList = &FatMemList.MemList;
/* Set up the memory allocation request; we want room for
* the Task structure and the requested stack size plus
* any arguments to pass to the new Task.
*/
LocalMemList->ml_NumEntries = 2;
LocalMemList->ml_ME[0].me_Reqs = MEMF_ANY|MEMF_PUBLIC|MEMF_CLEAR;
LocalMemList->ml_ME[0].me_Length = sizeof(struct Task);
LocalMemList->ml_ME[1].me_Reqs = MEMF_ANY|MEMF_CLEAR;
LocalMemList->ml_ME[1].me_Length = StackSize + NumArgs * sizeof(LONG);
/* Try the allocation. */
if(MemList = AllocEntry(LocalMemList))
{
/* Check if the allocation did work. */
if((ULONG)MemList & 0x80000000)
{
/* Strip the failure bit. */
MemList = (struct MemList *)((ULONG)MemList & ~0x80000000);
}
else
{
/* So we got the memory for the Task. */
Task = (struct Task *)MemList->ml_ME[0].me_Addr;
/* Initialize the Task data structure. We will not
* copy the name to a separate buffer, it is assumed
* that the name pointer will remain valid for the
* entire life time of this Task.
*/
Task->tc_Node.ln_Pri = Priority;
Task->tc_Node.ln_Type = NT_TASK;
Task->tc_Node.ln_Name = Name;
Task->tc_SPLower = MemList->ml_ME[1].me_Addr;
Task->tc_SPUpper = (APTR)((ULONG)Task->tc_SPLower + MemList->ml_ME[1].me_Length);
Task->tc_SPReg = (APTR)((ULONG)Task->tc_SPUpper - NumArgs * sizeof(LONG));
/* Add the memory to be released when the Task exits. */
NewList(&Task->tc_MemEntry);
AddTail(&Task->tc_MemEntry,(struct Node *)MemList);
/* If there are any arguments to pass to the Task,
* copy them onto the stack.
*/
if(NumArgs > 0)
{
va_list VarArgs;
va_start(VarArgs,NumArgs);
CopyMem(VarArgs,Task->tc_SPReg,NumArgs * sizeof(LONG));
va_end(VarArgs);
}
/* Try to launch the Task... */
Task = AddTask(Task,(APTR)Entry,NULL);
}
/* Check if the Task could be launched and clean
* up if it couldn't.
*/
if(Task == NULL && MemList != NULL)
FreeEntry(MemList);
}
return(Task);
}
/* ChangeWindowPtr(APTR *Old,APTR New):
*
* Change the pr_WindowPtr entry and return the old value.
*/
VOID
ChangeWindowPtr(APTR *Old,APTR New)
{
struct Process *CurrentProcess;
CurrentProcess = (struct Process *)FindTask(NULL);
*Old = CurrentProcess->pr_WindowPtr;
CurrentProcess->pr_WindowPtr = New;
}
/* RestoreWindowPtr(APTR Old):
*
* Restore the pr_WindowPtr to whatever it was poiting to.
*/
VOID
RestoreWindowPtr(APTR Old)
{
((struct Process *)FindTask(NULL))->pr_WindowPtr = Old;
}
/* DisableDOSRequesters(APTR *WindowPtr):
*
* Turn off the AmigaDOS requesters.
*/
VOID
DisableDOSRequesters(APTR *WindowPtr)
{
ChangeWindowPtr(WindowPtr,(APTR)-1);
}
/* EnableDOSRequesters(APTR WindowPtr):
*
* Turn the AmigaDOS requesters back on.
*/
VOID
EnableDOSRequesters(APTR WindowPtr)
{
RestoreWindowPtr(WindowPtr);
}
/* SpeechSynthesizerAvailable():
*
* Checks if the speech synthesizer is available for use.
*/
BOOL
SpeechSynthesizerAvailable()
{
struct Library *LocalTranslatorBase;
BOOL SpeechAvailable;
SpeechAvailable = FALSE;
if(LocalTranslatorBase = OpenLibrary("translator.library",0))
{
struct narrator_rb NarratorRequest;
memset(&NarratorRequest,0,sizeof(NarratorRequest));
NarratorRequest.message.io_Message.mn_Length = sizeof(NarratorRequest);
if(!OpenDevice("narrator.device",0,(struct IORequest *)&NarratorRequest,NULL))
{
SpeechAvailable = TRUE;
CloseDevice((struct IORequest *)&NarratorRequest);
}
CloseLibrary(LocalTranslatorBase);
}
return(SpeechAvailable);
}
/* CurrentTimeToStamp(struct DateStamp *Stamp):
*
* A replacement for DateStamp().
*/
VOID
CurrentTimeToStamp(struct DateStamp *Stamp)
{
struct timeval Now;
GetSysTime(&Now);
Stamp->ds_Days = Now.tv_secs / (24 * 60 * 60);
Stamp->ds_Minute = (Now.tv_secs % (24 * 60 * 60)) / 60;
Stamp->ds_Tick = (Now.tv_secs % 60) * TICKS_PER_SECOND + (TICKS_PER_SECOND * Now.tv_micro) / MILLION;
}
/* SmartOpenDiskFont(struct TextAttr *TextAttr):
*
* Opens a disk-resident font. Does not require diskfont.library
* to be open all the time while the program is running.
*/
struct TextFont *
SmartOpenDiskFont(struct TextAttr *TextAttr)
{
struct TextFont *Result;
Result = NULL;
if(DiskfontBase = OpenLibrary("diskfont.library",0))
{
Result = OpenDiskFont(TextAttr);
CloseLibrary(DiskfontBase);
}
if(!Result)
Result = OpenFont(TextAttr);
return(Result);
}
/* ArmLimit(ULONG SecondsToGo):
*
* Arm the limit counter. We remember the time when the limit
* will be exceeded.
*/
VOID
ArmLimit(ULONG SecondsToGo)
{
GetSysTime(&LimitTime);
LimitTime.tv_secs += SecondsToGo;
}
/* DisarmLimit():
*
* Clear the limit counter.
*/
VOID
DisarmLimit()
{
memset(&LimitTime,0,sizeof(LimitTime));
}
/* CheckLimit():
*
* Check if the limit counter has been triggered.
* If triggered, clear the limit counter.
*/
BOOL
CheckLimit()
{
BOOL Triggered;
Triggered = FALSE;
if(LimitTime.tv_secs > 0 || LimitTime.tv_micro > 0)
{
struct timeval Now;
GetSysTime(&Now);
if(-CmpTime(&Now,&LimitTime) >= 0)
Triggered = TRUE;
}
if(Triggered)
DisarmLimit();
return(Triggered);
}